﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ADDDF.Infrastructure
{
    public class CompositeValue : IValueObject
    {
        private Dictionary<string, object> _values;
        private int? _hashCode;

        public CompositeValue(IDictionary<string, object> nameAndValuePairs)
        {
            _values = new Dictionary<string, object>(nameAndValuePairs);
            _hashCode = null;
        }

        public object GetValue(string name)
        {
            return _values[name];
        }

        #region Equality Tests

        public override bool Equals(object another)
        {
            if (another == null)
                return false;

            if (object.ReferenceEquals(this, another))
                return true;

            CompositeValue b = another as CompositeValue;

            if (b == null)
                return false;

            if (_values.Count != b._values.Count)
                return false;

            foreach (string key in _values.Keys)
            {
                if (!b._values.ContainsKey(key))
                    return false;

                object aVal = _values[key];
                object bVal = b._values[key];

                if (aVal != null)
                {
                    if (!aVal.Equals(bVal))
                        return false;
                }
                else if (bVal != null)
                {
                    if(!bVal.Equals(aVal))
                        return false;
                }
                
                // aVal == bVal == null is considered equal.
            }

            return true;
        }

        public override int GetHashCode()
        {
            if (!_hashCode.HasValue)
            {
                int code = 0;
                foreach (object value in _values.Values)
                    code = code ^ value.GetHashCode();
                _hashCode = code;
            }
            return _hashCode.Value;
        }

        #endregion  
    }
}
